//////////////////////////////////////////////////////////////////////////
#include <Gfed/GameDescription.hpp>
#include "createprojectdialog.h"
#include <Core/Core.hpp>
#include <QDir>
#include <QFile>

// Converting to Qt json handling.
// Didn't know it existed, was added in Qt5 thankfully.
#include <QJsonArray>
#include <QJsonValue>
#include <QJsonObject>
#include <QJsonDocument>


//////////////////////////////////////////////////////////////////////////
Gfed::GameDescription::GameDescription()
:	Modified( false )
{
}


//////////////////////////////////////////////////////////////////////////
bool Gfed::GameDescription::create( QWidget* parent )
{
	CreateProjectDialog	createDlg( parent );

	if( createDlg.exec() )
	{
		DLOG( INFO ) << "Creating a new game description: " << createDlg.gameName().toUtf8().data();
		GameName		=	createDlg.gameName();
		BaseDirectory	=	createDlg.baseDirectory();

		// Save the initial game description.
		QDir		baseDir( BaseDirectory );
		QFileInfo	filename( baseDir, GameName + ".gfp" );

		return save( filename.absoluteFilePath() );
	}
	else
	{
		DLOG( INFO ) << "Canceled new game creation.";
	}

	return false;
}


bool Gfed::GameDescription::close()
{
	return false;
}


bool Gfed::GameDescription::load( const QString& filename )
{
	// TEST: Switching to Qt5 Json.
	QFile	jsonFile;
	jsonFile.setFileName( filename );

	if( jsonFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
	{
		QJsonDocument	jsonDoc	=	jsonDoc.fromJson( jsonFile.readAll().data() );
		if( jsonDoc.isNull() )
			return false;

		if( jsonDoc.isObject() )
		{
			QJsonObject	project	=	jsonDoc.object();
			GameName		=	project.value( "GameName" ).toString();
			BaseDirectory	=	project.value( "BaseDirectory" ).toString();

			Packages.clear();
			QJsonArray	packages	=	project.value( "Packages" ).toArray();
			for( const auto& pkg : packages )
			{
				QJsonArray		pair	=	pkg.toArray();
				MountPoint_t	mp( pair.at( 0 ).toString(), pair.at( 1 ).toString() );
				Packages.push_back( mp );
			}

			Overrides.clear();
			QJsonArray	overrides	=	project.value( "Overrides" ).toArray();
			for( const auto& ovr : overrides )
			{
				QJsonArray		pair	=	ovr.toArray();
				MountPoint_t	mp( pair.at( 0 ).toString(), pair.at( 1 ).toString() );
				Overrides.push_back( mp );
			}
			
			return true;
		}
	}
	return false;
}


bool Gfed::GameDescription::save( const QString& filename )
{
	{
		QJsonArray	pkgVector;
		for( const auto& pkg : Packages )
		{
			QJsonArray	entries;
			entries.push_back( QJsonValue( pkg.first ) );
			entries.push_back( QJsonValue( pkg.second ) );
			pkgVector.push_back( entries );
		}
	
		QJsonArray	ovrVector;
		for( const auto& ovr : Overrides )
		{
			QJsonArray	entries;
			entries.push_back( QJsonValue( ovr.first ) );
			entries.push_back( QJsonValue( ovr.second ) );
			ovrVector.push_back( entries );
		}
	
		QJsonObject	project;
		project.insert( "GameName", QJsonValue( GameName ) );
		project.insert( "BaseDirectory", QJsonValue( BaseDirectory ) );
		project.insert( "Packages", pkgVector );
		project.insert( "Overrides", ovrVector );
		
		QJsonDocument	projDoc( project );

		QFile	jsonFile;
		jsonFile.setFileName( filename );
		
		if( jsonFile.open( QIODevice::WriteOnly | QIODevice::Text ) )
		{
			jsonFile.write( projDoc.toJson() );
			return true;
		}
		return false;
	}

#if 0
	// Build the packages and overrides arrays.
	JSONArray	pkgArray;
	for( auto& pkg : Packages )
	{
		JSONArray	entries;
		entries.push_back( new JSONValue( pkg.first.toStdWString() ) );
		entries.push_back( new JSONValue( pkg.second.toStdWString() ) );
		pkgArray.push_back( new JSONValue( entries ) );
	}

	JSONArray	ovrArray;
	for( auto& ovr : Overrides )
	{
		JSONArray	entries;
		entries.push_back( new JSONValue( ovr.first.toStdWString() ) );
		entries.push_back( new JSONValue( ovr.second.toStdWString() ) );
		ovrArray.push_back( new JSONValue( entries ) );
	}

	// Build the top level project object.
	JSONObject		project;
	project[ L"GameName" ]		=	new JSONValue( GameName.toStdWString() );
	project[ L"BaseDirectory" ]	=	new JSONValue( BaseDirectory.toStdWString() );
	project[ L"Packages" ]		=	new JSONValue( pkgArray );
	project[ L"Overrides" ]		=	new JSONValue( ovrArray );

	// Finally wrap it all up.
	JSONObject		projRoot;
	projRoot[ L"Project" ]		=	new JSONValue( project );
	JSONValue		outProject( projRoot );
	std::wstring	saveString	=	outProject.Stringify() + L"\n";

	std::ofstream	outStream( filename.toUtf8().data() );
	if( outStream.bad() )
		return false;

	JsonHelpers::Reformat( saveString );
	outStream << string_cast< std::string >( saveString );

	return true;
#endif
}
